_this = null

(()->
    $.fn.extend
        tree: (options)->
            new Tree this, options
) jQuery

class Tree
    defaultOptions:
        speed: 3,
        sort: false,
        order: false,
        orderConfirm: 'Da li želite premestite kategoriju?',
        language: {}

    constructor: (@element, options)->
        _this = this

        @options = $.extend @defaultOptions, options

        @changedULs = []
        @container  = @element.parent()
        @element.find('.tree').parent().addClass('parent')
            .each ()->
                _this.createToggler().prependTo this

        if @options.sort or @options.order
            @toolbar = $('<div class="toolbar">')
                .insertBefore @element

        @initSortable() if @options.sort
        @initOrdable()  if @options.order

    createToggler: ()->
        $('<span class="toggle">').click ()->
            $(this).parent().toggleClass 'opened'

    initSortable: ()->
        _this = this

        # create toolbar button
        lngUpdateSort  = @getLang('Ažuriraj redosled')
        @btnUpdateSort = $('<input type="button" class="save-sort" value="'+lngUpdateSort+'">')
            .attr 'disabled', 'disabled'
            .attr 'title', lngUpdateSort
            .appendTo @toolbar
            .data 'tree', this
            .click ()->
                Tree = $(this).data 'tree'                
                Tree.options.sort.call Tree, $(Tree.changedULs)
                $(this).attr 'disabled', 'disabled'
                Tree.changedULs = []

        # init jQuery sortable
        uls = _this.element.find '.tree'
        uls = uls.add @element

        # create handles
        uls.children('li').each ()->
            $(this).append('<span class="tree-sort-handle" title="'+_this.getLang('Sortiraj')+'">')

        _this.changedULs = []
        uls.sortable
            placeholder:          'tree-sort-placeholder',
            handle:               '.tree-sort-handle',
            forcePlaceholderSize: true,
            axis:                 'y',
            start: (e, ui)->
                _this.container.addClass 'tree-sorting'

            stop:  (e, ui)->
                _this.container.removeClass 'tree-sorting'
                changed = _this.element.data 'changed'
                if changed
                    _this.changedULs.push $(this)
                    _this.btnUpdateSort.removeAttr 'disabled'
                    _this.element.data 'changed', false

            change: (e, ui)->
                _this.element.data 'changed', true

    initOrdable: ()->
        _this = this

        # get LIs
        lis = _this.element.find 'li'
        
        # create handles
        lis.each ()->
            $('<span>')
                .attr 'class', 'tree-reorder-handle'
                .attr 'title', _this.getLang('Premesti kategoriju')
                .appendTo this
        
        # create root droppable
        root = $ '<div class="tree-drop-root">'
            .text _this.getLang('Osnovna kategorija')
            .insertBefore _this.element

        # init drag-drop
        lis.draggable
            handle: '.tree-reorder-handle',
            revert: 'invalid',
            cursorAt: 
                right:0,
                bottom: 0
            start: (e, ui)->
                _this.container.addClass 'tree-ordering'

            stop: ()->
                _this.container.removeClass 'tree-ordering'

        dropFunction = (li, parent)->
            if confirm(_this.options.orderConfirm)
                _this.options.order.call _this, li, parent
            else
                li.removeAttr 'style'

        root.droppable
            accept: '.tree .ui-draggable-dragging',
            hoverClass: 'tree-reorder-hover',
            drop: (e, ui)->
                dropFunction ui.helper, null

        lis.droppable
            accept: '.tree li.ui-draggable-dragging',
            hoverClass: 'tree-reorder-hover',
            drop: (e, ui)->
                dropFunction ui.helper, $(this)

    getLang: (key)->
        lang = @options.language[key]
        return if lang? then lang else key